﻿#include <Sys\RenderUnit\SysRenderDatagram\PRIMITIVERD.HPP>
#include <Render\Render_Win32\Render_Win32_OpenGL\RENDER_WIN32_OPENGL.HPP>
#include <Sys\RenderUnit\SYSDDCLASSID.HPP>
#include <Sys\RenderUnit\SysDatagramDisposal_OpenGL\VERTEXREGISTRYDDOPENGL.HPP>
#include <Sys\RenderUnit\SysDatagramDisposal_OpenGL\POSTDRAWDDOPENGL.HPP>
#include <SLIST.HPP>

using namespace CxxlMan;
using namespace Cxxl3D;

class CPostDrawDDOpenGL:public IPostDrawDDOpenGL
{
  Smart_Ptr<SList<IPostDrawNotice,true> > m_IPostDrawNotice_Ptr;

  virtual void cxxlFASTCALL Add(const CxxlMan::Smart_Ptr<IPostDrawNotice> &IPostDrawNotice_Arg)
  {
    m_IPostDrawNotice_Ptr->Push_Back(IPostDrawNotice_Arg);
  }
  virtual void cxxlFASTCALL Del(const CxxlMan::Smart_Ptr<IPostDrawNotice> &IPostDrawNotice_Arg)
  {
    m_IPostDrawNotice_Ptr->Delete(IPostDrawNotice_Arg);
  }

  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterOpengl> &IRenderDatagramDisposalCenter_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, const CxxlMan::CSmart_Ptr<Matrix4x4> &ViewMatrix_Arg)
  {
    return true;
  }

public:
  // Constructor
  CPostDrawDDOpenGL()
    :cxxlObject(CxxlMan::Spirit_Easy),
     m_IPostDrawNotice_Ptr(new SList<IPostDrawNotice,true>,this)
  {
  }

  // Destructor
  ~CPostDrawDDOpenGL()
  {
  }

  void cxxlFASTCALL Notice()
  {
    Smart_Ptr<cxxlList<IPostDrawNotice> > IPostDrawNotice_List =
      m_IPostDrawNotice_Ptr->cxxlList_Create();

    unsigned long Count = IPostDrawNotice_List->GetCount();
    IPostDrawNotice_List->ResetPT(toHead);
    for(Smart_Ptr<IPostDrawNotice> IPostDrawNotice_Ptr = (*IPostDrawNotice_List)++; 
      Count > 0; 
      --Count,IPostDrawNotice_Ptr = (*IPostDrawNotice_List)++)
    {
      IPostDrawNotice_Ptr->Notice();
    }    
  }
};


cxxlObject *cxxlFASTCALL New_CPostDrawDDOpenGL()
{
  return new CPostDrawDDOpenGL;
}

/*********************************************************/

class CTrianglesStripDD_OpenGL:public IDatagramDisposal_OpenGL
{
  Smart_Ptr<IVertexRegistryDDOpenGL> IVertexRegistryDDOpenGL_Ptr;
  Smart_Ptr<CPostDrawDDOpenGL> CPostDrawDDOpenGL_Ptr;


  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterOpengl> &IRenderDatagramDisposalCenter_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, const CxxlMan::CSmart_Ptr<Matrix4x4> &ViewMatrix_Arg)
  {
    // 第一次被叫用才會取得
    if(IVertexRegistryDDOpenGL_Ptr.isNULL())
      IVertexRegistryDDOpenGL_Ptr =  Smart_Cast<IVertexRegistryDDOpenGL>(IRenderDatagramDisposalCenter_Arg->GetIDatagramDisposal_OpenGL(IVertexRegistryOpenGL_ClassID));

    // 第一次被叫用才會取得
    if(CPostDrawDDOpenGL_Ptr.isNULL())
      CPostDrawDDOpenGL_Ptr =  Smart_Cast<CPostDrawDDOpenGL>(IRenderDatagramDisposalCenter_Arg->GetIDatagramDisposal_OpenGL(IPostDrawDDOpenGL_ClassID));


    // 取得目前登記作用中的 IVertexDD
    Smart_Ptr<IVertexDD> IVertexDD_Ptr = IVertexRegistryDDOpenGL_Ptr->Get();

    C3D_USINT VertexNum, IndexNum;
    IVertexDD_Ptr->Get_VertexNum_IndexNum(VertexNum, IndexNum);

    Smart_Ptr<ITrianglesStripRD> ITrianglesStripRD_Ptr = (ITrianglesStripRD*)GetDefaultInterface(IRenderDatagram_Arg);

    if(VertexNum && IndexNum)
    {
      glDrawElements(
	  	  GL_TRIANGLE_STRIP, // 指定所要畫的基本圖形種類
	  	  IndexNum, // 有幾個索引值
	  	  GL_UNSIGNED_SHORT, // 索引值的型態
	  	  0 // 不再傳入陣列的指標, 而是傳用索引值起始的位移
      );
    }

    CPostDrawDDOpenGL_Ptr->Notice();
    return true;
  }


public:
  // Consteructor
  CTrianglesStripDD_OpenGL()
    :cxxlObject(Spirit_Easy),
    IVertexRegistryDDOpenGL_Ptr(NULL,this),
    CPostDrawDDOpenGL_Ptr(NULL,this)
  {
  }

  // Desteructor
  virtual ~CTrianglesStripDD_OpenGL()
  {
  }
};

cxxlObject *cxxlFASTCALL New_CTrianglesStripDD_OpenGL()
{
  return new CTrianglesStripDD_OpenGL;
}

/*********************************************************/

class CTrianglesListDD_OpenGL:public IDatagramDisposal_OpenGL
{
  Smart_Ptr<IVertexRegistryDDOpenGL> IVertexRegistryDDOpenGL_Ptr;
  Smart_Ptr<CPostDrawDDOpenGL> CPostDrawDDOpenGL_Ptr;

  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterOpengl> &IRenderDatagramDisposalCenter_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, const CxxlMan::CSmart_Ptr<Matrix4x4> &ViewMatrix_Arg)
  {
    // 第一次被叫用才會取得
    if(IVertexRegistryDDOpenGL_Ptr.isNULL())
      IVertexRegistryDDOpenGL_Ptr =  Smart_Cast<IVertexRegistryDDOpenGL>(IRenderDatagramDisposalCenter_Arg->GetIDatagramDisposal_OpenGL(IVertexRegistryOpenGL_ClassID));

    // 第一次被叫用才會取得
    if(CPostDrawDDOpenGL_Ptr.isNULL())
      CPostDrawDDOpenGL_Ptr =  Smart_Cast<CPostDrawDDOpenGL>(IRenderDatagramDisposalCenter_Arg->GetIDatagramDisposal_OpenGL(IPostDrawDDOpenGL_ClassID));

    // 取得目前登記作用中的 IVertexDD
    Smart_Ptr<IVertexDD> IVertexDD_Ptr = IVertexRegistryDDOpenGL_Ptr->Get();

    C3D_USINT VertexNum, IndexNum;
    IVertexDD_Ptr->Get_VertexNum_IndexNum(VertexNum, IndexNum);

    Smart_Ptr<ITrianglesListRD> ITrianglesListRD_Ptr = (ITrianglesListRD*)GetDefaultInterface(IRenderDatagram_Arg);

    if(VertexNum && IndexNum)
    {
      glDrawElements(
	  	  GL_TRIANGLES, // 指定所要畫的基本圖形種類
        IndexNum,     // 有幾個索引值
	  	  GL_UNSIGNED_SHORT, // 索引值的型態
	  	  0 // 不再傳入陣列的指標, 而是傳用索引值起始的位移
      );

    }

    CPostDrawDDOpenGL_Ptr->Notice();
    return true;
  }


public:
  // Consteructor
  CTrianglesListDD_OpenGL()
    :cxxlObject(Spirit_Easy),
     IVertexRegistryDDOpenGL_Ptr(NULL,this),
     CPostDrawDDOpenGL_Ptr(NULL,this)
 {
  }

  // Desteructor
  virtual ~CTrianglesListDD_OpenGL()
  {
  }
};

cxxlObject *cxxlFASTCALL New_CTrianglesListDD_OpenGL()
{
  return new CTrianglesListDD_OpenGL;
}